package com.calefk.util {
    
    import com.calefk.core.Library;
    import flash.display.MovieClip;
    import flash.events.Event;
    import flash.media.Sound;
    import flash.media.SoundChannel;
    import flash.media.SoundTransform;
    import flash.utils.Dictionary;
    import flash.utils.getDefinitionByName;
    
	/**
     * Representa un solo sonido, puede tener varios canales
     * @author 
     */
    
    public class SoundFx {
        
        private var mChannels:Array;
        private var mChannelsLoops :Array; // volumen , start , 
        
        private var mName    :String;
        private var mSound   :Sound;
        /**
         * Esta variable perimite que no exista lag 
         * al momento de reproducir cualquier sonido
         */
        private var mChannelFixed:SoundChannel;

        public function SoundFx(name:String , library:Library = null) {
            mName = name;
            var soundClass:Class;
            
            // create class
            if (library == null) {
                soundClass = getDefinitionByName(name) as Class;
            } else {
                soundClass = library.getClass(name) as Class;
            }
            
			mSound = new soundClass();
            
            mChannels = new Array();
            mChannelsLoops = new Array();
            
            // fixed para que no produzca lag
            //mChannelFixed = mSound.play(0 , 1 , new SoundTransform(0));
            //mChannelFixed.addEventListener(Event.SOUND_COMPLETE, onSoundCompleteFixed, false, 0, true);
        }
        
        private function onSoundCompleteFixed(e:Event):void { 
            mChannelFixed.removeEventListener(Event.SOUND_COMPLETE, onSoundCompleteFixed);   
        }
        
        public function playFast():void {
            mSound.play();
        }
        
        public function play(volumen:Number = 1 , eventComplete:Function = null) {
            var trans:SoundTransform = new SoundTransform(volumen, 0);             
            var channel:SoundChannel = mSound.play(0 , 1 , trans);
            channel.addEventListener(Event.SOUND_COMPLETE, onSoundCompleteInternal, false, 0, true);
            mChannels.push({channel:channel , eventComplete:eventComplete , position:0 , isPaused:false});
        }
        
        private function onSoundCompleteInternal(e:Event):void {
            var channel:SoundChannel = e.target as SoundChannel;
            channel.stop();
            channel.removeEventListener(Event.SOUND_COMPLETE , onSoundCompleteInternal);
            
            // buscar canal con propiedades
            var channelObj:* = null;
			for (var k:int = 0; k < mChannels.length; k++ ) {
                var o:* = mChannels[k];
                if (o.channel == channel) {
                    channelObj = o;
                    mChannels.splice(k , 1);
                    break;
                }
            }
            
            // call event
            if (channelObj.eventComplete != null) {
                channelObj.eventComplete(this);
            }
		}
        
        public function playMulti(loop:int = 2, volumen:Number = 1 , eventComplete:Function = null):void {
            var trans:SoundTransform = new SoundTransform(volumen, 0);             
            var channel:SoundChannel = mSound.play(0 , 1 , trans);
            channel.addEventListener(Event.SOUND_COMPLETE, onSoundCompleteInternalLoop, false, 0, true);
            mChannelsLoops.push({channel:channel, loop:loop , volumen:volumen , eventComplete:eventComplete , position:0 , isPaused:false});           
        }
        
        private function onSoundCompleteInternalLoop(e:Event):void {
            var channel:SoundChannel = e.target as SoundChannel;
            channel.removeEventListener(Event.SOUND_COMPLETE , onSoundCompleteInternal);
            
            // buscar canal loop
            var channelLoop:* = null;
            var index:int = -1;
            
            for (var k:int = 0; k < mChannelsLoops.length; k++) {
                var o:* = mChannelsLoops[k];
                if (o.channel == channel) {
                    channelLoop = o;
                    index = k;
                    break;
                }
            }
            // verificar si reproducir nuevamente o terminar e invocar el evento
            if (channelLoop) {
                channelLoop.loop--;
                if (channelLoop.loop == 0) {
                    // remover y llamar evento
                    if (index >= 0 ) {
                        mChannelsLoops.splice(index, 1);
                    }
                    // call event
                    if (channelLoop.eventComplete != null) {
                        channelLoop.eventComplete(this);   
                    }
                } else {
                    // reproducir nuevamente
                    var transb:SoundTransform = new SoundTransform(channelLoop.volumen, 0);             
                    var channelb:SoundChannel = mSound.play(0 , 1 , transb);
                    channelb.addEventListener(Event.SOUND_COMPLETE, onSoundCompleteInternalLoop, false, 0, true);
                    channelLoop.channel = channelb;
                }
            }
        }
        
        public function pause():void {
            for each (var channelObj:* in mChannels) {
                if (! channelObj.isPaused) {
                    channelObj.position = channelObj.channel.position;
                    // remove reference channel
                    channelObj.channel.stop();
                    channelObj.channel.removeEventListener(Event.SOUND_COMPLETE , onSoundCompleteInternal);
                    channelObj.channel = null;
                    // change flag
                    channelObj.isPaused = true;
                }
            }
            
            for each (var channelObj2:* in mChannelsLoops) {
                if (! channelObj2.isPaused) {
                    channelObj2.position = channelObj2.channel.position;
                    // remove reference channel
                    channelObj2.channel.stop();
                    channelObj2.channel.removeEventListener(Event.SOUND_COMPLETE , onSoundCompleteInternal);
                    channelObj2.channel = null;
                    // hcange flag
                    channelObj2.isPaused = true;
                }
            }                     
        }
        
        public function unpause():void {
            var channel:SoundChannel;
            var trans:SoundTransform;
            
            for each (var channelObj:* in mChannels) {
                if (channelObj.isPaused) {
                    // play again sound
                    trans = new SoundTransform(channelObj.volumen, 0);             
                    channel = mSound.play(channelObj.position , 1 , trans);
                    channel.addEventListener(Event.SOUND_COMPLETE, onSoundCompleteInternal , false, 0, true);
                    channelObj.channel = channel;
                    // change flag
                    channelObj.isPaused = false;
                }
            }
            
            for each (var channelObj2:* in mChannelsLoops) {
                if (channelObj2.isPaused) {
                    // play again sound
                    trans = new SoundTransform(channelObj2.volumen, 0);             
                    channel = mSound.play(channelObj2.position , 1 , trans);
                    channel.addEventListener(Event.SOUND_COMPLETE, onSoundCompleteInternalLoop, false, 0, true);
                    channelObj2.channel = channel;
                    // change flag
                    channelObj2.isPaused = false;
                }
            }              
        }
        
        public function stop():void {
            for each (var channelObj:* in mChannels) {
                channelObj.channel.stop();
                channelObj.channel.removeEventListener(Event.SOUND_COMPLETE , onSoundCompleteInternal);
            }
            mChannels.splice(0 , mChannels.length);
            
            for each (var channelObj2:* in mChannelsLoops) {
                channelObj2.channel.stop();
                channelObj2.channel.removeEventListener(Event.SOUND_COMPLETE , onSoundCompleteInternalLoop);
            }
            mChannelsLoops.splice(0 , mChannelsLoops.length);
        }
    }
}